package com.yuedou.api.util.sql;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author Li
 * @data 2022/1/6 14:50
 * @description 创建数据库表工具类
 */
@Slf4j
@Component
@Service
public class CreateTableUtil {

    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;
    @Value("${spring.datasource.url}")
    private String url;
    @Value("${spring.datasource.username}")
    private String username;
    @Value("${spring.datasource.password}")
    private String password;

    private static CreateTableUtil createTableUtil;

    /**
     * 初始化注入的 service
     */
    @PostConstruct
    public void init() {
        createTableUtil = this;
        createTableUtil.driverClassName = this.driverClassName;
        createTableUtil.url = this.url;
        createTableUtil.username = this.username;
        createTableUtil.password = this.password;

    }


    /*String*/
    public static final String TYPE_STRING = "String";

    /*Integer*/
    public static final String TYPE_INTEGER = "Integer";

    /*Double*/
    public static final String TYPE_DOUBLE = "Double";

    /*Date*/
    public static final String TYPE_Date = "Date";

    /*BigDecimal*/
    public static final String TYPE_BigDecimal = "BigDecimal";

    /*text*/
    public static final String TYPE_text = "text";

    /**
     * 连接MySQL数据库
     */
    public static Map<String, Object> connectMySQL(){
        Connection connection = null;
        Statement statement = null;
        Map<String, Object> map = new HashMap<>();
        try {
            // 连接数据库
            Class.forName("com.mysql.cj.jdbc.Driver"); //(driverClassName);
            // 获取数据库连接
            connection = DriverManager.getConnection(createTableUtil.url, createTableUtil.username, createTableUtil.password);
            // 根据连接获取可执行Statement
            statement = connection.createStatement();

            map.put("connection",connection);
            map.put("statement",statement);
            return map;
        }catch (Exception e){
            e.printStackTrace();
            log.error("CreateTable 类中，连接数据库错误！");
        }
        return null;
    }

    /**
     * 执行SQL语句
     * @param tableName
     * @return
     */
    public static String executeSQL(String sqlFile,String tableName) throws SQLException {
        Connection conn = null;
        Statement state = null;
        try {
            Map<String, Object> map = connectMySQL();
            if (map == null){
                return "获取数据库连接失败...";
            }
            // 获取数据库连接
            conn = (Connection)map.get("connection");
            // 获取SQL执行环境
            state = (Statement)map.get("statement");
            // 获取数据库表名
            ResultSet tables = conn.getMetaData().getTables(null, null, tableName, null);
            // 是否存在表
            if (tables.next()){
                // 存在不创建-存在删除表（强制同步）
                String sqlDropTable = createSQLDropTable(tableName);
                System.out.println("--------------删除表sql开始---------------");
                System.out.println(sqlDropTable);
                System.out.println("--------------删除表sql结束---------------");
                // 删除表
                state.executeUpdate(sqlDropTable);
            }
            String sql = SqlFileExecutor.loadSqlToStr(sqlFile,tableName);  //  createSQL(chargerOrder);
            System.out.println("--------------创建表sql开始---------------");
            System.out.println(sql);
            System.out.println("--------------创建表sql结束---------------");
            // 创建表
            state.executeUpdate(sql);

            // 修改为已同步
//            SysMeter meter = new SysMeter();
//            meter.setId(sysMeter.getId());
//            meter.setSynState("1");
//            createTable.sysMeterService.updateById(meter);

        }catch (Exception e){
            e.printStackTrace();
            return "表"+ tableName +"同步失败!";
        }finally {
            // 释放资源
            state.close();
            conn.close();
        }
        return "表"+ tableName +"同步成功";
    }

    public static void main(String[] args) {
        try {
            CreateTableUtil createTableUtil = new CreateTableUtil();
            createTableUtil.executeSQL("D:\\Project\\Java\\yuedou\\charger_order.sql","testName");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 数据库是否存在表名
     * @param tableName
     * @return true 存在 & 错误
     * @return false 不存在
     */
    public static boolean existsTable(String tableName) throws SQLException {
        Connection conn = null;
        Statement state = null;
        // 获取数据库连接和SQL执行环境
        try {
            Map<String, Object> map = connectMySQL();
            if (map!=null){
                return true;
            }
            // 获取数据库连接
            conn = (Connection)map.get("connection");
            // 获取SQL执行环境
            state = (Statement)map.get("statement");
            // 获取数据库表名
            ResultSet tables = conn.getMetaData().getTables(null, null,tableName, null);
            if (tables.next()){
                return true;
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error("验证数据库表名是否能存在错误！");
            return true;
        }finally {
            state.close();
            conn.close();
        }
        return false;
    }

//    /**
//     * 创建生成表的SQL
//     * @param chargerOrder
//     * @param tableName
//     * @return
//     */
//    public static String createSQL(ChargerOrder chargerOrder,String tableName){
//        // 创建主键集合
//        List<String> priKeyList = new ArrayList<String>();
//        // 创建 StringBuffer 拼接sql
//        StringBuffer sb = new StringBuffer();
//        sb.append("CREATE TABLE `"+ tableName +"` (\n");
//        List<SysMeterAttached> meterInfo = sysMeter.getMeterInfo();
//        for (int i = 0; i < meterInfo.size(); i++) {
//            // 当前条数据
//            SysMeterAttached sma = meterInfo.get(i);
//            // 判断数据类型
//            String fieldType = judgeDataType(sma.getFieldType());
//            sb.append(""+ sma.getFieldName() +"");
//            if ("double".equals(fieldType)){
//                // 特殊处理 `age` double(23,0) DEFAULT NULL COMMENT '年龄',
//                // 追加列
//                sb.append(" "+fieldType+"("+sma.getFieldLength()+","+ sma.getDecimalPoint() +") ");
//            }else if ("decimal".equals(fieldType)){
//                // 追加列
//                sb.append(" "+fieldType+"("+sma.getFieldLength()+","+ sma.getDecimalPoint() +") ");
//            }else {
//                // 追加列
//                sb.append(" "+fieldType+"("+sma.getFieldLength()+") ");
//            }
//
//            // 判断是否为主键 - 等于1是主键
//            if ("1".equals(sma.getPrimaryKey())){
//                // 字段名称放进去
//                priKeyList.add(sma.getFieldName());
//                // 判断是否允许为空 等于1是允许为空; 只有不为空的时候，需要设置
//                if (!"1".equals(sma.getIsNull())){
//                    sb.append("NOT NULL COMMENT '"+sma.getFieldRemark()+"',\n");
//                }
//                // 如果到了最后一条，并且只有一个主键时
//                if (i >= meterInfo.size()-1 && priKeyList.size() == 1){
//                    sb.append("PRIMARY KEY (`"+ priKeyList.get(0) +"`)");
//                    sb.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;");
//
//                }else if (i >= meterInfo.size() -1 && priKeyList.size() > 1){
//                    // 最后一条，并且存在多个主键时
//                    sb.append("PRIMARY KEY (");
//                    // 遍历主键集合
//                    for (int j = 0; j < priKeyList.size(); j++) {
//                        // 最后一个时
//                        if (j == priKeyList.size() -1){
//                            sb.append("`"+ priKeyList.get(j) +"`) USING BTREE \n");
//                        }else {
//                            sb.append("`"+ priKeyList.get(j) +"`,");
//                        }
//                    }
//                    sb.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;");
//                }
//                // 非主键，直接判断是否允许为空
//            }else {
//                // 存在主键，并且为最后一个了
//                if (priKeyList.size() > 0 && i >= meterInfo.size() -1 ){
//                    // 判断是否为空 if是可以为空
//                    if ("1".equals(sma.getIsNull())){
//                        sb.append("DEFAULT NULL COMMENT '"+ sma.getFieldRemark() +"',\n");
//                    }else {
//                        sb.append("NOT NULL COMMENT '"+ sma.getFieldRemark() +"',\n");
//                    }
//                    // 表示只有一个主键
//                    if (priKeyList.size() == 1){
//                        sb.append("PRIMARY KEY (`"+ priKeyList.get(0) +"`)\n");
//                        sb.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;");
//                    }else {
//                        // 最后一条，并且存在多个主键时
//                        sb.append("PRIMARY KEY (");
//                        // 遍历主键集合
//                        for (int j = 0; j < priKeyList.size(); j++) {
//                            // 最后一个时
//                            if (j == priKeyList.size() -1){
//                                sb.append("`"+ priKeyList.get(j) +"`) USING BTREE \n");
//                            }else {
//                                sb.append("`"+ priKeyList.get(j) +"`,");
//                            }
//                        }
//                        sb.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;");
//                    }
//                }else {
//                    // 没有就追加 判断是否为空
//                    if ("1".equals(sma.getIsNull())){
//                        sb.append("DEFAULT NULL COMMENT '"+ sma.getFieldRemark() +"',\n");
//                    }else {
//                        sb.append("NOT NULL COMMENT '"+ sma.getFieldRemark() +"',\n");
//                    }
//                }
//            }
//        }
//        return sb.toString();
//    }

    /**
     * 删除表SQL
     * @param tableName
     * @return
     */
    public static String createSQLDropTable(String tableName){
        return "DROP TABLE "+ tableName +"";
    }

    /**
     * 判断类型
     * varchar
     * int
     * double
     * datetime
     * decimal
     * text
     *
     * @param type
     * @return
     */
    private static String judgeDataType(String type){
        switch (type){
            case TYPE_STRING:
                return "varchar";
            case TYPE_INTEGER:
                return "int";
            case TYPE_DOUBLE:
                return "double";
            case TYPE_Date:
                return "datetime";
            case TYPE_BigDecimal:
                return "decimal";
            case TYPE_text:
                return "text";
            default :
                return "varchar";
        }
    };
}

